import { MeasureType } from "@/constants/enums/logisticsTemplate";
import { Button, Card, Checkbox, Form, Input, InputNumber, Modal, Popover, Radio, Space, Table, message } from "antd";
import { ColumnsType } from "antd/es/table";
import dayjs from "dayjs";
import { useEffect, useState } from "react";
import { useModel, Access } from '@umijs/max'
import { useRequest } from "ahooks";
import { queryCityOptions } from "@/services/common";
import { DownOutlined, RightOutlined } from "@ant-design/icons";
import { removeLogisticsTemplateArea, saveLogisticsTemplate } from "@/services/logisticsTemplate";

type Checked = Record<string, {
  checked: boolean
  indeterminate: boolean
  value: {label: string, value: string}
  children: Checked
}>

let currentId: any = ''
let currentCities: {label: string, value: string}[] = []
let delIds: string[] = []
const EditLogisticsTemplate: React.FC = () => {
  const [editLogisticsTemplateForm] = Form.useForm()
  const [areaList, setAreaList] = useState<LogisticsTemplateArea[]>([])
  const { closeCurrentTab } = useModel('global')
  const cityOptions = useRequest(queryCityOptions)
  const [open, setOpen] = useState(false)
  const [cityCountMap, setCityCountMap] = useState<Checked>({})
  const [allChecked, setAllChecked] = useState(false)
  const [allIndeterminate, setAllIndeterminate] = useState(false)
  const saveTemplate = useRequest(saveLogisticsTemplate, {manual: true})
  const delTemplateAreaReq = useRequest(removeLogisticsTemplateArea, {manual: true})

  const delArea = (record: LogisticsTemplateArea) => {
    if (record.templateAreaId) {
      delIds.push(record.templateAreaId)
    }
    setAreaList(old => old.filter(it => it.templateAreaId ? it.templateAreaId !== record.templateAreaId : it._fakeId !== record._fakeId))
  }
  const addArea = () => {
    currentId = ''
    currentCities = []
    setOpen(true)
  }
  const editArea = (record: LogisticsTemplateArea) => {
    currentId = record.templateAreaId || record._fakeId
    currentCities = record.area as {label: string, value: string}[]
    setOpen(true)
  }
  const cancel = () => {
    const event = new CustomEvent('refreshTemplateList')
    window.dispatchEvent(event)
    closeCurrentTab('/mall/logistics/template')
  }
  const save = () => {
    editLogisticsTemplateForm
    .validateFields()
    .then((values: any) => {
      if (areaList.length < 1) {
        message.error('请指定可配送区域和运费')
        return
      }
      if (areaList.some(it => it.renewNum === null || it.renewPrice === null || it.startNum === null || it.startPrice === null)) {
        message.error('请完善运费信息')
        return
      }
      const _saveParams: Partial<LogisticsTemplate> = {
        ...values,
        area: areaList.map(it => ({
          ...it,
          area: JSON.stringify(it.area),
        }))
      }
      saveTemplate
      .runAsync(_saveParams)
      .then(() => {
        message.success('保存成功')
        if (values.templateId) {
          delIds.forEach(id => {
            delTemplateAreaReq.run({templateId: values.templateId, templateAreaId: id})
          })
        }
        cancel()
      })
    })
  }

  const columns: ColumnsType<LogisticsTemplateArea> = [
    {
      title: '可配送区域',
      dataIndex: 'area',
      render: val => {
        return val?.map((it: any) => it.label).join(',')
      }
    },
    {
      title: '',
      key: 'operations',
      width: 120,
      render: (_, record) => {
        return <Space>
          <a onClick={() => editArea(record)}>修改</a>
          <a onClick={() => delArea(record)}>删除</a>
        </Space>
      }
    },
    {
      title: '首件(个)',
      dataIndex: 'startNum',
      width: 120,
      render: (startNum, record) => {
        return <InputNumber defaultValue={startNum} onChange={value => record.startNum = value} controls={false} precision={0} min={1} />
      }
    },
    {
      title: '运费(元)',
      dataIndex: 'startPrice',
      width: 120,
      render: (startPrice, record) => {
        return <InputNumber defaultValue={startPrice} onChange={value => record.startPrice = value} controls={false} precision={2} min={0} />
      }
    },
    {
      title: '续件(个)',
      dataIndex: 'renewNum',
      width: 120,
      render: (renewNum, record) => {
        return <InputNumber defaultValue={renewNum} onChange={value => record.renewNum = value} controls={false} precision={0} min={1} />
      }
    },
    {
      title: '续费(元)',
      dataIndex: 'renewPrice',
      width: 120,
      render: (renewPrice, record) => {
        return <InputNumber defaultValue={renewPrice} onChange={value => record.renewPrice = value} controls={false} precision={2} min={0} />
      }
    },
  ]

  const onAreaChange = (checked: boolean, city: CityData) => {
    const cityId = `${city.value.substring(0, 4)}00`
    const provinceId = `${city.value.substring(0, 2)}0000`
    const _province: Checked['x'] = {...cityCountMap[provinceId]}
    const _city: Checked['x'] = {..._province.children[cityId]}
    _city.children[city.value].checked = checked

    if (Object.values(_city.children).every(it => it.checked)) {
      _city.checked = true
      _city.indeterminate = false
    } else if (Object.values(_city.children).some(it => it.checked)) {
      _city.checked = false
      _city.indeterminate = true
    } else {
      _city.checked = false
      _city.indeterminate = false
    }

    _province.children[cityId] = _city
    if (Object.values(_province.children).every(it => it.checked)) {
      _province.checked = true
      _province.indeterminate = false
    } else if (Object.values(_province.children).some(it => it.checked || it.indeterminate)) {
      _province.checked = false
      _province.indeterminate = true
    } else {
      _province.checked = false
      _province.indeterminate = false
    }
    setCityCountMap(old => ({...old, [provinceId]: _province}))
  }
  const onCityChange = (checked: boolean, city: CityData) => {
    const provinceId = `${city.value.substring(0, 2)}0000`
    const target = {...cityCountMap[provinceId].children[city.value]}
    target.checked = checked
    target.indeterminate = false
    Object.values(target.children).forEach(item => {
      const _children: Checked = {}
      Object.values(item.children).forEach(it => {
        _children[it.value.value] = {
          checked: checked,
          indeterminate: false,
          value: it.value,
          children: {}
        }
      })
      target.children[item.value.value] = {
        checked: checked,
        indeterminate: false,
        value: item.value,
        children: _children,
      }
    })
    const province: Checked['x'] = {
      ...cityCountMap[provinceId],
      children: {
        ...cityCountMap[provinceId].children,
        [city.value]: target,
      }
    }
    if (Object.values(province.children).every(it => it.checked)) {
      province.checked = true
      province.indeterminate = false
    } else if (Object.values(province.children).some(it => it.checked)) {
      province.checked = false
      province.indeterminate = true
    } else {
      province.checked = false
      province.indeterminate = false
    }
    setCityCountMap(old => ({...old, [provinceId]: province}))
  }
  const onProvinceChange = (checked: boolean, city: CityData) => {
    const target = {...cityCountMap[city.value]}
    target.checked = checked
    target.indeterminate = false
    // 遍历城市
    Object.values(target.children).forEach(item => {
      const _children: Checked = {}
      // 遍历区
      Object.values(item.children).forEach(it => {
        _children[it.value.value] = {
          checked: checked,
          indeterminate: false,
          value: it.value,
          children: {}
        }
      })
      target.children[item.value.value] = {
        checked: checked,
        indeterminate: false,
        value: item.value,
        children: _children
      }
    })
    setCityCountMap(old => ({...old, [city.value]: target}))
  }
  const onAllChange = (checked: boolean) => {
    const _map: Checked = {}
    Object.values(cityCountMap).forEach(province => {
      const _cityMap: Checked = {}
      Object.values(province.children).forEach(city => {
        const _AreaMap: Checked = {}
        Object.values(city.children).forEach(area => {
          _AreaMap[area.value.value] = {
            checked: checked,
            indeterminate: false,
            value: area.value,
            children: {},
          }
        })
        _cityMap[city.value.value] = {
          checked: checked,
          indeterminate: false,
          value: city.value,
          children: _AreaMap,
        }
      })
      _map[province.value.value] = {
        checked: checked,
        indeterminate: false,
        value: province.value,
        children: _cityMap,
      }
    })
    setCityCountMap(_map)
  }
  const onCancel = () => {
    setOpen(false)
  }
  const onOk = () => {
    const _provinces: {label: string, value: string}[] = []
    const _cities: {label: string, value: string}[] = []
    const _areas: {label: string, value: string}[] = []
    Object.values(cityCountMap).forEach(province => {
      if (province.checked) { // 省份被选择，不需要遍历城市
        _provinces.push(province.value)
      } else if (province.indeterminate) { // 省份被半选择，遍历城市
        Object.values(province.children).forEach(city => {
          if (city.checked) { // 城市被选择，不需要遍历地区
            _cities.push(city.value)
          } else if (city.indeterminate) { // 城市被半选择，遍历地区
            Object.values(city.children).forEach(area => {
              if (area.checked) { // 地区被选择
                _areas.push(area.value)
              }
            })
          }
        })
      }
    })
    if (_provinces.length < 1 && _cities.length < 1 && _areas.length < 1) {
      message.error('请选择配送区域')
      return
    }
    const _area = [..._provinces, ..._cities, ..._areas]
    const _repeatArea = _area.find( // 遍历当前选择的区域
      currentArea => areaList.some( // 遍历已经选择的区域
        it => it.templateAreaId !== currentId && it._fakeId !== currentId && (it.area as {label: string, value: string}[]).some(alreadyArea => alreadyArea.value === currentArea.value)
      )
    )
    if (_repeatArea) {
      message.error(`不可重复选择相同地区: ${_repeatArea.label}`)
      return
    }
    if (currentId) { // 修改
      setAreaList(areaList.map(it => {
        if (it.templateAreaId === currentId || it._fakeId === currentId) {
          return {...it, area: _area}
        }
        return it
      }))
    } else { // 新增
      setAreaList(areaList.concat([{
        _fakeId: dayjs().valueOf(),
        area: _area,
        startNum: 1,
        startPrice: 1,
        renewNum: 1,
        renewPrice: 1,
      }]))
    }
    onCancel()
  }

  useEffect(() => {
    if (Object.values(cityCountMap).every(province => province.checked)) {
      setAllChecked(true)
      setAllIndeterminate(false)
    } else if (Object.values(cityCountMap).some(province => province.checked || province.indeterminate)) {
      setAllChecked(false)
      setAllIndeterminate(true)
    } else {
      setAllChecked(false)
      setAllIndeterminate(false)
    }
  }, [cityCountMap]);
  useEffect(() => {
    if (open) {
      const _map: Checked = {}
      cityOptions.data?.data.forEach(province => {
        const _checked = currentCities.some(it => it.value === province.value)
        if (_checked) { // 省份被选中，其下的所有城市、地区全部选中
          const _cities: Checked = {}
          province.children.forEach(city => {
            const _areas: Checked = {}
            city.children.forEach(area => {
              _areas[area.value] = {
                checked: true,
                indeterminate: false,
                value: {label: area.label, value: area.value},
                children: {},
              }
            })
            _cities[city.value] = {
              checked: true,
              indeterminate: false,
              value: {label: city.label, value: city.value},
              children: _areas,
            }
          })
          _map[province.value] = {
            checked: true,
            indeterminate: false,
            value: {label: province.label, value: province.value},
            children: _cities,
          }
        } else { // 省份未选中，遍历其下城市
          const _cities: Checked = {}
          let provinceIndeterminate: boolean = false
          province.children.forEach(city => {
            const _cityChecked = currentCities.some(it => it.value === city.value)
            if (_cityChecked) { // 城市被选中，其下的所有地区全部选中
              provinceIndeterminate = true
              const _areas: Checked = {}
              city.children.forEach(area => {
                _areas[area.value] = {
                  checked: true,
                  indeterminate: false,
                  value: {label: area.label, value: area.value},
                  children: {},
                }
              })
              _cities[city.value] = {
                checked: true,
                indeterminate: false,
                value: {label: city.label, value: city.value},
                children: _areas,
              }
            } else { // 城市未选中，遍历其下地区
              const _areas: Checked = {}
              let cityIndeterminate: boolean = false
              city.children.forEach(area => {
                const _cityChecked = currentCities.some(it => it.value === area.value)
                if (_cityChecked) {
                  provinceIndeterminate = true
                  cityIndeterminate = true
                }
                _areas[area.value] = {
                  checked: _cityChecked,
                  indeterminate: false,
                  value: {label: area.label, value: area.value},
                  children: {},
                }
              })
              _cities[city.value] = {
                checked: false,
                indeterminate: cityIndeterminate,
                value: {label: city.label, value: city.value},
                children: _areas,
              }
            }
          })
          _map[province.value] = {
            checked: false,
            indeterminate: provinceIndeterminate,
            value: {label: province.label, value: province.value},
            children: _cities,
          }
        }
      })
      setCityCountMap(_map)
    }
  }, [open])
  useEffect(() => {
    delIds = []
    const _dataStr = sessionStorage.getItem('logisticsTemplateData')
    if (_dataStr) {
      const _data = JSON.parse(_dataStr) as LogisticsTemplate
      editLogisticsTemplateForm.setFieldsValue({
        templateId: _data.templateId,
        tplName: _data.tplName,
        measureType: _data.measureType,
      })
      setAreaList(_data.area?.map(it => ({
        ...it,
        area: JSON.parse(it.area as string),
      })))
      sessionStorage.removeItem('logisticsTemplateData')
    }
  }, [])

  return <Card>
    <Form
      form={editLogisticsTemplateForm}
      name='editLogisticsTemplateForm'
      labelCol={{flex: '120px'}}
      initialValues={{measureType: MeasureType.件数}}
    >
      <Form.Item name='templateId' noStyle>
        <Input hidden />
      </Form.Item>
      <Form.Item label='模板名称' name='tplName' rules={[{required: true, message: '请输入模板名称'}]}>
        <Input maxLength={20} style={{width: 320}} />
      </Form.Item>
      <Form.Item label='计费方式' name='measureType'>
        <Radio.Group
          // options={enum2options(MeasureType)}
          options={[
            {label: '件数', value: MeasureType.件数},
            // {label: '重量', value: MeasureType.重量},
          ]}
        />
      </Form.Item>
      <Form.Item label='配送区域'>
        <Table<LogisticsTemplateArea>
          rowKey={record => `${record.templateAreaId}-${record._fakeId}`}
          columns={columns}
          dataSource={areaList}
          pagination={false}
        />
        <Button type="primary" style={{marginTop: 8}} onClick={addArea}>指定可配送区域和运费</Button>
      </Form.Item>
      <Form.Item label=' ' colon={false}>
        <Space>
          <Button type="primary" onClick={save} loading={saveTemplate.loading}>保存</Button>
          <Button type="primary" ghost onClick={cancel}>取消</Button>
        </Space>
      </Form.Item>
    </Form>
    <Modal
      title='选择配送区域'
      open={open}
      width={720}
      onCancel={onCancel}
      footer={<div className="flex items-center">
        <Checkbox checked={allChecked} indeterminate={allIndeterminate} onChange={({target}) => onAllChange(target.checked)}>全选</Checkbox>
        <Button style={{marginLeft: 'auto', marginRight: 8}} onClick={onCancel}>取消</Button>
        <Button type="primary" onClick={onOk}>确定</Button>
      </div>}
    >
      <div className="w-full grid grid-cols-4 gap-2">
        {
          cityOptions.data?.data?.map(province => {
            return <div key={province.value}>
              <Access accessible={province.children.length > 0} fallback={<Checkbox
                checked={cityCountMap[province.value]?.checked}
                onChange={({target}) => onProvinceChange(target.checked, province)}
              >{province.label}</Checkbox>}>
                <Popover placement="right" content={province.children.map(city => {
                  return <div key={city.value}>
                    <Access accessible={city.children.length > 0} fallback={<Checkbox
                      checked={cityCountMap[city.value]?.checked}
                      onChange={({target}) => onCityChange(target.checked, city)}
                    >{city.label}</Checkbox>}>
                      <Popover placement="right" content={city.children.map(area => <div key={area.value}>
                        <Checkbox
                          checked={cityCountMap[province.value]?.children[city.value].children[area.value]?.checked}
                          onChange={({target}) => onAreaChange(target.checked, area)}
                        >{area.label}</Checkbox>
                      </div>)}>
                        <Checkbox
                          checked={cityCountMap[province.value]?.children[city.value]?.checked}
                          indeterminate={cityCountMap[province.value]?.children[city.value]?.indeterminate}
                          onChange={({target}) => onCityChange(target.checked, city)}
                        >
                          <span>{city.label}</span>
                          <RightOutlined className="text-xs ml-1" />
                        </Checkbox>
                      </Popover>
                    </Access>
                  </div>
                })}>
                  <Checkbox
                    checked={cityCountMap[province.value]?.checked}
                    indeterminate={cityCountMap[province.value]?.indeterminate}
                    onChange={({target}) => onProvinceChange(target.checked, province)}
                  >
                    <span>{province.label}</span>
                    <DownOutlined className="text-xs ml-1" />
                  </Checkbox>
                </Popover>
              </Access>
            </div>
          })
        }
      </div>
    </Modal>
  </Card>
}

export default EditLogisticsTemplate
